#include "json.hpp"
#include "Scok.hpp"
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <thread>
#include <condition_variable>
#include <queue>
#include "Comm.hpp"

struct Info
{
    string str;
    int fd;
};

static const int NUM = 64;
class EpollServer
{
private:
    Sock _listensock;
    int _epfd;
    mutex mutexA;
    mutex mutexB;
    condition_variable cond1;
    condition_variable cond2;
    thread t2; 
    thread t3;
    queue<Info> queueA;
    queue<Info> queueB;
public:

    void thread_entry2()
    {
        
        while(true)
        {
            struct Info info;
            {
                unique_lock<mutex> lock(mutexA);
                cond1.wait(lock, [&](){
                   return !queueA.empty();
                });
                info = queueA.front();
                queueA.pop();
            }

            Request req(info.str);
            std::string str = req.handler();
            info.str = str;

            {
                unique_lock<mutex> lock(mutexB);
                queueB.push(info);
            }
        }
    }

    void thread_entry3()
    {
        while(true)
        {
            struct Info info;
            {
                unique_lock<mutex> lock(mutexB);
                cond2.wait( lock, [&](){
                   return !queueB.empty();
                });
            }

            info = queueB.front();
            queueB.pop();
            string str = info.str;
            write(info.fd, str.c_str(), str.size());
        }
    }

    EpollServer()
    :t2(&EpollServer::thread_entry2, this)
    ,t3(&EpollServer::thread_entry3, this)
    {
        _epfd = epoll_create(NUM);
        if(_epfd < 0 )
        {
            perror("epoll error");
            exit(-1);
        }
    }

    void Init()
    {
        _listensock.Socket();
        _listensock.Bind();
        _listensock.Listen();

        std::cout << "开始监听了" << std::endl;
    } 

    void Run()
    {
        struct epoll_event event;
        event.data.fd = _listensock.Fd();
        event.events = EPOLLIN;
        epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock.Fd(), &event);

        struct epoll_event evs[NUM];
        while(true)
        {
            int n = epoll_wait(_epfd, evs, NUM, -1);
            if(n > 0)
            {
                Dispatcher(evs, n);
            }
        }
    }

    void SetNonBlock(int fd)
    {
        int f = fcntl(fd, F_GETFL);
        if(f < 0)
        {
            perror("error");
        }

        fcntl(fd, F_SETFL, f | O_NONBLOCK);
    }

    void Dispatcher(struct epoll_event evs[], int n )
    {
        for(int i = 0; i < n; i++)
        {
            if(evs[i].data.fd == _listensock.Fd())
            {
                std::cout << "获得链接" << std::endl;
                Aceptor();
            }
            else
            {
                Recver(evs[i].data.fd);
            }
        }
    }

    void Aceptor()
    {
        int fd = _listensock.Accept();
        SetNonBlock(fd);
        struct epoll_event event;
        event.data.fd = fd;
        event.events = EPOLLIN | EPOLLET;

        epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &event);
    }

    void Recver(int fd)
    {
        std::cout << "Recver" << std::endl;
        while(true)
        {
            char buffer[1024];
            int n =  read(fd, buffer, sizeof(buffer));
            if( n > 0)
            {
                //处理数据
                buffer[n] = 0;
                string str(buffer);
                struct Info info;
                info.str = str;
                info.fd = fd;

                {
                    unique_lock<mutex> lock(mutexA);
                    queueA.push(info);
                }

                cond1.notify_all();
               // write(fd, str.c_str(), str.size());
            }
            else if(n == 0)
            {
                //对端退出
                epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
                close(fd);
            }
            else 
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    break; //未就绪
                }

                epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
                close(fd);
            }
        }
    }    
};